#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>

//#define LOG_NDEBUG 0
#define LOG_NDDEBUG 0
#define LOG_NIDEBUG 0

#define LOG_TAG "voiceCore"
#include <cutils/atomic.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
#include <utils/SystemClock.h>

#include <cutils/sched_policy.h>
#include <pthread.h>
#include <sched.h>
#include <sys/resource.h>
#if defined(HAVE_PRCTL)
#include <sys/prctl.h>
#endif

#include <media/AudioSystem.h>
#include <media/AudioRecord.h>
#include <media/AudioTrack.h>
#include <media/mediarecorder.h>
#include <media/AudioEffect.h>
#include <audio_effects/effect_aec.h>
#include <system/audio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "SKP_Silk_SDK_API.h"
#include "SKP_Silk_SigProc_FIX.h"


#define __android_log_print(a,b,fmt,arg...) printf(fmt,##arg)
//#define DEBUG_SILK8 0

#define USE_CODEC       1
#define RINGSIZE         333
using namespace android;

enum voiceState {
    INITED = 1,
    STARTED,
    RELEASED
};

typedef struct {
    uint64_t lastPlayTime;
	int trackFrameSize;//number
	int rnb;
	int wnb;
    pthread_cond_t wait;
	unsigned char *adata;//RINGSIZE * trackFrameSize
}audioRingBuf_t;

typedef struct {
    int serverSocket;
    int port;
    enum voiceState state;
    sockaddr_storage remote;


    AudioTrack track;
    AudioRecord record;
    pthread_t trackThread;
    pthread_t recordThread;
    AudioEffect *aec;
    int sampleRate;
    int sampleCount;
    int exitPending;
    int recordFrameSize;
    void (*send)(unsigned char *buf, int len);
    char use_videostreamtype_flag;
}audio_device_s;


static int g_track_started = 0;
static audio_device_s *g_audioDevice = NULL;
static audioRingBuf_t g_abuf = {0, 0, 0, 0, PTHREAD_COND_INITIALIZER, NULL};
FILE * g_commustat_fp;
//////

    /* Define codec specific settings */
#define MAX_BYTES_ENC_PER_FRAME     250 // Equals peak bitrate of 100 kbps
#define MAX_BYTES_DEC_PER_FRAME     1024

#define MAX_INPUT_FRAMES        5
#define MAX_LBRR_DELAY          2
#define MAX_FRAME_LENGTH        480

#define	MAX_FRAME			160

    SKP_int32 encSizeBytes;
    void      *psEnc;

    /* default settings */
    SKP_int   fs_kHz = 8;
    SKP_int   targetRate_bps = 20000;
    SKP_int   packetSize_ms = 20;
    SKP_int   frameSizeReadFromFile_ms = 20;
    SKP_int   packetLoss_perc = 0, smplsSinceLastPacket;
    SKP_int   INBandFec_enabled = 0, DTX_enabled = 0, quiet = 0;
    SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder
    static int g_codec_open = 0;


/* decoder parameters */

    char payloadToDec[    MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
    short out[ ( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ], *outPtr;
    SKP_int32 decSizeBytes;
    void      *psDec;
    SKP_SILK_SDK_DecControlStruct DecControl;


void printhex(const char *data_acp, int data_len_ai)
{
	int i = 0;

	if(data_acp == NULL)	return;

	for(; i < data_len_ai; i++){
		printf("%02x ", *(unsigned char *)(data_acp + i));
		if((i + 1) % 20== 0)	printf("\n");
		else if((i + 1) % 5 == 0)	printf("  ");
	}

	printf("\n\n");
	return;
}





int codec_open()
{
        int ret;

        if (g_codec_open++ != 0)
            return 0;

        /* Set the samplingrate that is requested for the output */
        DecControl.sampleRate = 16000;

        /* Create decoder */
        ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );
        if( ret ) {
            __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                "\n!!!!!!!! SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );
        }
#ifdef DEBUG_SILK8
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                "### INIT Decoder decSizeBytes = %d\n", decSizeBytes);
#endif
        psDec = malloc( decSizeBytes );

        /* Reset decoder */
        ret = SKP_Silk_SDK_InitDecoder( psDec );
        if( ret ) {
            __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                "\n!!!!!!!! SKP_Silk_InitDecoder returned %d", ret );
        }


        /* Create Encoder */
        ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );
        if( ret ) {
            __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                "\n!!!!!!!! SKP_Silk_SDK_Get_Encoder_Size returned %d", ret );
        }
#ifdef DEBUG_SILK8
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                "### INIT Encoder encSizeBytes = %d\n", encSizeBytes);
#endif
        psEnc = malloc( encSizeBytes );

        /* Reset Encoder */
        ret = SKP_Silk_SDK_InitEncoder( psEnc, &encControl );
        if( ret ) {
            __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                "\n!!!!!!!! SKP_Silk_SDK_InitEncoder returned %d", ret );
        }

        /* Set Encoder parameters */
        encControl.sampleRate           = fs_kHz * 1000;
        encControl.packetSize           = packetSize_ms * fs_kHz;
        encControl.packetLossPercentage = packetLoss_perc;
        encControl.useInBandFEC         = INBandFec_enabled;
        encControl.useDTX               = DTX_enabled;
        encControl.complexity           = 0;
        encControl.bitRate              = targetRate_bps;

        return 0;

}

void Print_Decode_Error_Msg(int errcode) {
	switch (errcode) {
		case SKP_SILK_DEC_WRONG_SAMPLING_FREQUENCY:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nOutput sampling frequency lower than internal decoded sampling frequency\n", errcode);
			break;
		case SKP_SILK_DEC_PAYLOAD_TOO_LARGE:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nPayload size exceeded the maximum allowed 1024 bytes\n", errcode);
			break;
		case SKP_SILK_DEC_PAYLOAD_ERROR:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nPayload has bit errors\n", errcode);
			break;
	}
}

void Print_Encode_Error_Msg(int errcode) {
	switch (errcode) {
		case SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nInput length is not a multiplum of 10 ms, or length is longer than the packet length\n", errcode);
			break;
		case SKP_SILK_ENC_FS_NOT_SUPPORTED:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nSampling frequency not 8000, 12000, 16000 or 24000 Hertz \n", errcode);
			break;
		case SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nPacket size not 20, 40, 60, 80 or 100 ms\n", errcode);
			break;
		case SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nAllocated payload buffer too short \n", errcode);
			break;
		case SKP_SILK_ENC_WRONG_LOSS_RATE:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nLoss rate not between 0 and 100 percent\n", errcode);
			break;
		case SKP_SILK_ENC_WRONG_COMPLEXITY_SETTING:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nComplexity setting not valid, use 0, 1 or 2\n", errcode);
			break;
		case SKP_SILK_ENC_WRONG_INBAND_FEC_SETTING:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nInband FEC setting not valid, use 0 or 1\n", errcode);
			break;
		case SKP_SILK_ENC_WRONG_DTX_SETTING:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nDTX setting not valid, use 0 or 1\n", errcode);
			break;
		case SKP_SILK_ENC_INTERNAL_ERROR:
			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
				"!!!!!!!!!!! Decode_Error_Message: %d\nInternal encoder error\n", errcode);
			break;
	}
}


int codec_encode( short *lin, int offset, char *encoded, int size)
{

        char     enc_payload[ MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES ];
        short    in[ MAX_FRAME_LENGTH * MAX_INPUT_FRAMES ];
        int ret,i,frsz=MAX_FRAME;
        SKP_int16 nBytes;
        unsigned int lin_pos = 0;

        if (!g_codec_open)
            return 0;

#ifdef DEBUG_SILK8
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                "encoding frame size: %d\toffset: %d\n", size, offset);
#endif


        for (i = 0; i < size; i+=MAX_FRAME) {
#ifdef DEBUG_SILK8
            __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                "encoding frame size: %d\toffset: %d i: %d\n", size, offset, i);
#endif

            /* max payload size */
            nBytes = MAX_BYTES_ENC_PER_FRAME * MAX_INPUT_FRAMES;

            ret = SKP_Silk_SDK_Encode( psEnc, &encControl, lin + i, (SKP_int16)frsz, (SKP_uint8 *)enc_payload, &nBytes );
            if( ret ) {
                __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                    "!!!!!!!! SKP_Silk_Encode returned: %d\n", ret);
                Print_Encode_Error_Msg(ret);
                break;
            }
#ifdef DEBUG_SILK8
                __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                    "Enocded nBytes: %d\n", nBytes);
#endif
            /* Write payload */
            //env->SetByteArrayRegion(encoded, RTP_HDR_SIZE+ lin_pos, nBytes, enc_payload);
            memcpy(encoded+lin_pos, enc_payload, nBytes);
            lin_pos += nBytes;
        }
#ifdef DEBUG_SILK8
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
            "encoding **END** frame size: %d\toffset: %d i: %d lin_pos: %d\n", size, offset, i, lin_pos);
#endif

        return lin_pos;
}

int codec_decode(char *encoded, short *lin, int size)
{
            char buffer [MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
            short output_buffer[( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ];
          SKP_int16   *outPtr;

            int ret;
            SKP_int16 len;
          int tot_len,frames;

            if (!g_codec_open)
                return 0;

#ifdef DEBUG_SILK8
            __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                "##### BEGIN DECODE ********  decoding frame size: %d\n", size);
#endif
            memcpy(buffer, encoded, size);
          outPtr = output_buffer;
            tot_len = 0;
          frames = 0;

          do {
                ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0,(SKP_uint8 *) buffer, size, outPtr,&len );
                if( ret ) {
                    __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                        "!!!!!!!! SKP_Silk_SDK_Decode returned: %d\n", ret);
                    Print_Decode_Error_Msg(ret);
                }
#ifdef DEBUG_SILK8
                __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
                    "##### DECODED length: %d\n\t Frame #: %d", len);
#endif
              frames++;
              outPtr  += len;
              tot_len += len;

          } while( DecControl.moreInternalDecoderFrames );
            printf("get frame = %d len= %d\n", frames, tot_len );
            memcpy(lin, output_buffer, tot_len*2);
            return tot_len;
}

int codec_close()
{

        if (--g_codec_open != 0)
            return 0;
        /* Free decoder */
        free( psDec );
        /* Free Encoder */
        free( psEnc );
    return 0;
}

//////////
uint64_t get_time_us()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);

    return (uint64_t)tv.tv_sec * 1000000ull + (uint64_t)tv.tv_usec;
}


int addAFrame(unsigned char *frame, int len)
{
    int offset = g_abuf.wnb * g_abuf.trackFrameSize;
    //ALOGD("%s E %d", __FUNCTION__, g_abuf.wnb);

    ALOGD("%s time: add to ring audio wnb %d, frame ok?%d\n", __FUNCTION__, g_abuf.wnb, *(int *)frame);
    memcpy(g_abuf.adata + offset, frame, len);

    g_abuf.wnb = (g_abuf.wnb + 1) % RINGSIZE;
    if(g_abuf.wnb == g_abuf.rnb){
        g_abuf.rnb = (g_abuf.rnb + 1) % RINGSIZE;
    }

    if(!g_track_started && (g_abuf.wnb - g_abuf.rnb) == 2){
        pthread_cond_signal(&(g_abuf.wait));
    }

    return 0;
}

unsigned long get_file_size(const char *path)
{
    unsigned long filesize = -1;
    struct stat statbuff;
    if(stat(path, &statbuff) < 0){
        return filesize;
    }else{
        filesize = statbuff.st_size;
    }
    return filesize;
}
void voice_setListener(void (*send)(unsigned char*, int))
{
    ALOGV("%s E\n", __FUNCTION__);

    if(send != NULL){
        g_audioDevice->send= send;
    }else{
        ALOGD("%s NULL listener\n", __FUNCTION__);
    }

    ALOGV("%s X\n", __FUNCTION__);
    return;
}

static void *newplayer(void *parm)
{
    audio_device_s * audioDevice = (audio_device_s *)parm;
    int sampleCount = audioDevice->sampleCount;

    char buf[50];
    int fd = -1;
    char *path = "/sdcard/test.amr";
    int ret = 0;
    int length = 0, toWrite;
    int16_t output[160*1000];
    int chances;
    int16_t framelen = 0;

    if((fd = open(path, O_RDONLY)) < 0){
        ALOGE("open file %s error:%s\n", path, strerror(errno));
        return NULL;
    }
    ALOGE("open file %s on %d\n", path, fd);
    ret = lseek(fd, 10, SEEK_SET);
    printf("seek ret = %d %s\n", ret, strerror(errno));

    while((ret = read(fd, &framelen, 2)) > 0){
        printf("get framelen %d\n", framelen);
        if(framelen > 0){
            ret = read(fd, buf, framelen);
            if(ret <= 0){
                printf("error read\n");
                return NULL;
            }
        }
        length = codec_decode(buf, output, ret);
        audioDevice->track.write(output, length);
        usleep(15000);

    }


    return NULL;

}
static void* voiceRecord(void *parm)
{
    audio_device_s * audioDevice = (audio_device_s *)parm;
    int sampleCount = audioDevice->sampleCount;
    int16_t input[sampleCount];
    int16_t one;
    int length = 0;
    int chances = 100;
    audioDevice->record.read(&one, sizeof(one));

    ALOGD("%s E\n", __FUNCTION__);
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);//see ANDROID_PRIORITY_BACKGROUND

    while(!audioDevice->exitPending){
        chances = 100;
        int toRead = sampleCount;

        while (--chances > 0 && (toRead > 0)) {
            AudioRecord::Buffer buffer;
            buffer.frameCount = toRead;

            status_t status = audioDevice->record.obtainBuffer(&buffer, 1);
            if (status == NO_ERROR) {
                int offset = sampleCount - toRead;
                memcpy(&input[offset], buffer.i8, buffer.size);
                //ALOGV("record cpyed %d", buffer.size);
                toRead -= buffer.frameCount;
                audioDevice->record.releaseBuffer(&buffer);
            } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
                ALOGE("cannot obtainBuffer from AudioRecord");
                return NULL;
            }
        }


#if USE_CODEC
        int32_t buffer[sampleCount + 3];
        length = codec_encode(input, 0, (char *)buffer, sampleCount);
        ALOGD("%s encode length=%d=0x%02x\n", __FUNCTION__, length, length);
        if (length <= 0) {
            ALOGE("encoder error");
            continue;
        }
#else
        int16_t *buffer = input;
        int length = sizeof(input);
#endif

    printhex((char *)buffer, length);


#if 1
int16_t output[sampleCount];

length = codec_decode((char *)buffer, (short *)output, length);
if(length <=0 ){
    ALOGE("track Error decode ret %d", length);
    memset(output, 0, sizeof(output));
}

int toWrite = sampleCount;
chances = 100;

while (--chances > 0 && (toWrite > 0)) {

    AudioTrack::Buffer buffer;
    buffer.frameCount = toWrite;
    //ALOGE("%s time : bf obtbuf seq %d",__FUNCTION__, recv_seq);

    status_t status = audioDevice->track.obtainBuffer(&buffer, 1);
    //ALOGE("%s time : af obtbuf seq %d",__FUNCTION__, recv_seq);
    if (status == NO_ERROR) {
        int offset = sampleCount - toWrite;
        memcpy(buffer.i8, &output[offset], buffer.size);
        ALOGV("track cpyed %d", buffer.size);
        toWrite -= buffer.frameCount;
        //ALOGE("%s time : bf release seq %d",__FUNCTION__, recv_seq);
        audioDevice->track.releaseBuffer(&buffer);
        //ALOGE("%s time : af release seq %d",__FUNCTION__, recv_seq);
    } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
        ALOGE("cannot write to AudioTrack");
        return NULL;
    } else {
        if(chances < 50){
            ALOGE("obtain failed.track reset read offset");
            g_abuf.rnb = (g_abuf.wnb == 0) ? RINGSIZE : (g_abuf.wnb - 1);
            break;
        }
        ALOGE("track obtain buf status %d", status);
    }
}
ALOGD("%s time : after play a frame", __FUNCTION__);



#endif

        ALOGV("record send socket %d\n", length);

    }

    ALOGD("%s X", __FUNCTION__);
    return NULL;
}

/*
return frame size
*/
int initAudioDevice(int port, char *codec, char *audioParm)
{
    int output = 0;
    int input = 0;
    int ret = 0;

    ALOGD("%s E\n", __FUNCTION__);

    //AudioSystem as;
    //as.setMode(AUDIO_MODE_IN_COMMUNICATION);

    if(g_audioDevice == NULL){
        g_audioDevice = new audio_device_s;
    }else{
        ALOGE("%s voicecore has inited", __FUNCTION__);
        return -1;
    }
    g_audioDevice->sampleRate = 16000;
    g_audioDevice->sampleCount = 160;
    g_audioDevice->exitPending = 1;

    g_track_started = 0;
    codec_open();

    if (AudioTrack::getMinFrameCount(&output,
        AUDIO_STREAM_MUSIC,
        g_audioDevice->sampleRate) != NO_ERROR || output <= 0 ||
        AudioRecord::getMinFrameCount(&input, g_audioDevice->sampleRate,
        AUDIO_FORMAT_PCM_16_BIT, 1) != NO_ERROR || input <= 0) {
        ALOGE("%s cannot compute frame count", __FUNCTION__);
        goto error1;
    }
    ALOGD("%s reported frame count: output %d, input %d", __FUNCTION__, output, input);

    if(input < g_audioDevice->sampleCount*2){
        input = g_audioDevice->sampleCount*2;
    }
    if(output < g_audioDevice->sampleCount*2){
        output = g_audioDevice->sampleCount*2;
    }

    ALOGD("%s change frame count: output %d, input %d\n", __FUNCTION__, output, input);

    // Initialize AudioTrack and AudioRecord.

    if (g_audioDevice->track.set(
        AUDIO_STREAM_MUSIC,
        g_audioDevice->sampleRate, AUDIO_FORMAT_PCM_16_BIT,
                AUDIO_CHANNEL_OUT_MONO, output) != NO_ERROR ||
            g_audioDevice->record.set(AUDIO_SOURCE_VOICE_COMMUNICATION, g_audioDevice->sampleRate, AUDIO_FORMAT_PCM_16_BIT,
                AUDIO_CHANNEL_IN_MONO, input) != NO_ERROR) {
        ALOGE("%s cannot initialize audio device", __FUNCTION__);
        goto error1;
    }
    ALOGD("latency: output %d, input %d\n", g_audioDevice->track.latency(), g_audioDevice->record.latency());

    g_abuf.rnb = 0;
    g_abuf.lastPlayTime = 0;
    g_abuf.wnb = 0;
    g_abuf.adata = (unsigned char*)::calloc(1, g_abuf.trackFrameSize * RINGSIZE);
    g_audioDevice->state = INITED;

    return g_audioDevice->recordFrameSize;
error1:
    if(g_audioDevice){
        delete g_audioDevice;
        g_audioDevice = NULL;
    }
    ALOGD("%s X error", __FUNCTION__);
    return -1;
}

int startAudio()
{
    int ret = 0;
    int retryTimes = 0;

    ALOGD("%s E", __FUNCTION__);

    if(!g_audioDevice){
        ret = -1;
        goto out;
    }else if(g_audioDevice->state == STARTED){
        ALOGD("%s has started", __FUNCTION__);
        return 0;
    }


    g_audioDevice->record.start();
    g_audioDevice->track.start();

	g_audioDevice->exitPending = 0;

    //create 2 thread for send and receive audio data.
    while((ret = ::pthread_create(&g_audioDevice->recordThread, NULL, newplayer, g_audioDevice)) == EAGAIN && retryTimes++ < 5);

    ALOGD("%s create record thread", __FUNCTION__);
    //while((ret = ::pthread_create(&g_audioDevice->recordThread, NULL, voiceRecord, g_audioDevice)) == EAGAIN && retryTimes++ < 5);
    if(ret){
        ALOGE("%s Create thread voiceRecord failed %d", __FUNCTION__, ret);
        goto out;
    }

    //usleep(1000000);
    g_audioDevice->state = STARTED;
out:
    ALOGD("%s X", __FUNCTION__);
    return ret;
}

int releaseAudioDevice()
{
    ALOGD("%s E", __FUNCTION__);
    //AudioSystem as;
    //as.setMode(AUDIO_MODE_NORMAL);
    codec_close();

    if(g_audioDevice){
        if(!g_audioDevice->exitPending){
            g_audioDevice->exitPending = 1;
            if(!g_track_started){
                pthread_cond_signal(&(g_abuf.wait));
            }

            pthread_join(g_audioDevice->trackThread, NULL);
            pthread_join(g_audioDevice->recordThread, NULL);
            g_audioDevice->record.stop();
            g_audioDevice->track.stop();
        }else{//XXX if not start,audio input device will not release.
        //work around for audio input device relealse.
        //need to find a better solution
            int16_t one;
            ALOGW("%s workaround,start first", __FUNCTION__);
            g_audioDevice->record.start();
            g_audioDevice->record.read(&one, sizeof(one));
            g_audioDevice->record.stop();
            g_audioDevice->track.start();
            g_audioDevice->track.stop();
        }
        delete g_audioDevice;
        g_audioDevice = NULL;
    }
    if(g_abuf.adata){
        free(g_abuf.adata);
        g_abuf.adata = NULL;
    }
    usleep(50000);
    ALOGD("%s X", __FUNCTION__);
    return 0;
}



void addaudio(unsigned char *voicebuf, int length)

{

    unsigned char buf[128];

    long long interval = 0;



/*

    int file_fd = open("/sdcard/test.amr", O_RDWR | O_CREAT | O_APPEND, 0777);

    if (file_fd < 0) {

        printf("cannot open file\n");

    }



    if(file_fd > 0){

        write(file_fd, (unsigned char *)voicebuf, length);

        close(file_fd);

    }

*/

    memcpy(buf + 4, voicebuf, length);

    *(unsigned int *)buf = 1;

    addAFrame(buf, length + 4);

    //interval = get_systime_ms() - LastTime;

    //LastTime = get_systime_ms();

    //printf("%s  interval= %lld\n", __FUNCTION__, interval);



}



int main(int argc, char *argv[])

{

    int ret = 0;

    int i = 0;

    if((ret = initAudioDevice(0, argv[1], argv[2])) >= 0){

        voice_setListener(addaudio);

        //sleep(1);

        printf("before start %d \n", ret);

        startAudio();

        getchar();

        i++;

    }else{

        printf("failed:%d\n", i);

        sleep(5);

        //break;

    }

    printf("before release\n");

    releaseAudioDevice();

    printf("ok:%d\n", i);

//   if(getchar() == 'q'){

//      break;

//   }





    printf("exit\n");

    return ret;

}




